package com.pulse.common.utils.sor.make;

import com.pulse.common.utils.sor.domain.SorInfo;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class MakeSor {

    public static ByteBuffer make(SorInfo info) {

        // 创建所有块的 ByteBuffer
        ByteBuffer mapBlock = MapMake.make(info);
        ByteBuffer genParamsBlock = GenParamsMake.make(info);
        ByteBuffer supParamsBlock = SupParamsMake.make(info);
        ByteBuffer fxdParamsBlock = FxdParamsMake.make(info);
        ByteBuffer keyEventsBlock = KeyEventsMake.make(info);
        ByteBuffer dataPtsBlock = DataPtsMake.make(info);
        ByteBuffer cksumBlock = CksumMake.make(info);

        // 计算 Map Block 中的块信息
        updateMapBlock(mapBlock, genParamsBlock, supParamsBlock, fxdParamsBlock, keyEventsBlock, dataPtsBlock, cksumBlock);

        // 将所有块合并到一个 ByteBuffer 中
        ByteBuffer fileBuffer = combineBlocks(mapBlock, genParamsBlock, supParamsBlock, fxdParamsBlock, keyEventsBlock, dataPtsBlock, cksumBlock);

        return fileBuffer;
    }

    private static void updateMapBlock(ByteBuffer mapBlock, ByteBuffer genParamsBlock, ByteBuffer supParamsBlock,
                                       ByteBuffer fxdParamsBlock, ByteBuffer keyEventsBlock, ByteBuffer dataPtsBlock, ByteBuffer cksumBlock) {
        // 计算每个块的大小
        int generalParamsSize = genParamsBlock.position();
        int supplierParamsSize = supParamsBlock.position();
        int fixedParamsSize = fxdParamsBlock.position();
        int keyEventsSize = keyEventsBlock.position();
        int dataPointsSize = dataPtsBlock.position();
        int cksumSize = cksumBlock.position();

        // 更新 Map Block 中的块信息
        mapBlock.position(12); // 跳过 Map Block ID、版本号和大小字段
        writeBlockInfo(mapBlock, GenParamsMake.GENERAL_PARAMS_BLOCK_ID, 200, generalParamsSize);
        writeBlockInfo(mapBlock, SupParamsMake.SUPPLIER_PARAMS_BLOCK_ID, 200, supplierParamsSize);
        writeBlockInfo(mapBlock, FxdParamsMake.FIXED_PARAMS_BLOCK_ID, 200, fixedParamsSize);
        writeBlockInfo(mapBlock, KeyEventsMake.KEY_EVENTS_BLOCK_ID, 200, keyEventsSize);
        writeBlockInfo(mapBlock, DataPtsMake.DATA_POINTS_BLOCK_ID, 200, dataPointsSize);
        writeBlockInfo(mapBlock, CksumMake.CK_SUM_BLOCK_ID, 200, cksumSize);

        // 更新 Map Block 的大小
        mapBlock.putInt(6, mapBlock.position()); // 将 Map Block 的大小写入第 8 字节
    }

    private static void writeBlockInfo(ByteBuffer buffer, String blockId, int revision, int size) {
        buffer.put(blockId.getBytes()); // 块 ID
        buffer.putShort((short) revision); // 版本号
        buffer.putInt(size); // 块大小
    }

    private static ByteBuffer combineBlocks(ByteBuffer mapBlock, ByteBuffer genParamsBlock, ByteBuffer supParamsBlock,
                                            ByteBuffer fxdParamsBlock, ByteBuffer keyEventsBlock, ByteBuffer dataPtsBlock, ByteBuffer cksumBlock) {
        // 计算总文件大小
        int totalSize = mapBlock.position() + genParamsBlock.position() +
                supParamsBlock.position() + fxdParamsBlock.position() + keyEventsBlock.position() +
                dataPtsBlock.position() + cksumBlock.position();

        // 创建合并后的 ByteBuffer
        ByteBuffer fileBuffer = ByteBuffer.allocate(totalSize);
        fileBuffer.order(ByteOrder.LITTLE_ENDIAN);

        // 将所有块写入合并后的 ByteBuffer
        fileBuffer.put(mapBlock.array(), 0, mapBlock.position());
        fileBuffer.put(genParamsBlock.array(), 0, genParamsBlock.position());
        fileBuffer.put(supParamsBlock.array(), 0, supParamsBlock.position());
        fileBuffer.put(fxdParamsBlock.array(), 0, fxdParamsBlock.position());
        fileBuffer.put(keyEventsBlock.array(), 0, keyEventsBlock.position());
        fileBuffer.put(dataPtsBlock.array(), 0, dataPtsBlock.position());
        fileBuffer.put(cksumBlock.array(), 0, cksumBlock.position());

        // 返回合并后的 ByteBuffer
        return fileBuffer;
    }
}
